(** Launching subprocesses synchronously and asynchronously. *)

(** Returns a string describing the given exit status. *)
val string_of_status : Unix.process_status -> string

(** {e run_blocking cmd_line start_cb stdout_cb stderr_cb stop_cb}

    Runs a subprocess, delivering its stdout and stderr to callbacks,
    and does not return until the subprocess terminates.

    When the process starts, passes its pid to start_cb. As it runs,
    passes lines from stdout and stderr to stdout_cb and stderr_cb
    respectively.  When it terminates, passes its exit status to stop_cb,
    and then also returns the exit status from this function.

    Note: All callbacks may be called from another thread, and so they
    must be threadsafe.
*)
val run_blocking :
  string -> (int -> unit) -> (string -> unit) -> (string -> unit) ->
  (Unix.process_status -> unit) -> Unix.process_status

(** Class for running a subprocess asynchronously, delivering its stdout
    and stderr to callbacks. *)
class runner :
  object
    (** Initializes the runner.  This launches a worker thread and
	returns immediately. *)
    method init : unit -> unit

    (** Deinitializes the runner.  This joins the worker thread, and so if
	a process is currently running, this will wait for that process to
	terminate. *)
    method deinit : unit -> unit

    (** Sets the callback to call whenever a process starts.  The param
	of the callback is the pid of the new process.

	If a process is already running, then this callback will not
	be used until the next time a process is run.

	The callback must be threadsafe. *)
    method set_start_cb : (int -> unit) -> unit

    (** Sets the callback to which lines of stdout should be passed. The
	param of the callback is a line of stdout, including the newline.

	If a process is already running, then this callback will not
	be used until the next time a process is run.
	
	The callback must be threadsafe. *)
    method set_stdout_cb : (string -> unit) -> unit

    (** Sets the callback to which lines of stderr should be passed. The
	param of the callback is a line of stderr, including the newline.

	If a process is already running, then this callback will not
	be used until the next time a process is run.
	
	The callback must be threadsafe. *)
    method set_stderr_cb : (string -> unit) -> unit

    (** Sets the callback to call whenever a process terminates.  The param
	of the callback is the exit status of the process.

	If a process is already running, then this callback will not be
	used until the next time a process is run.

	The callback must be threadsafe. *)
    method set_stop_cb : (Unix.process_status -> unit) -> unit
      
    (** Sets all callbacks to functions that do nothing.  *)
    method reset_callbacks : unit -> unit
      
    (** Returns true if a process is running. *)
    method is_running : bool

    (** Kills the current process if there is one. *)
    method kill : unit -> unit

    (** Runs a new process based on the given command line.
	
	If a process is already running, this call blocks until
	that process has terminated. *)
    method run : string -> unit
  end
